今天要來寫登入的 API 串接,取得 JWT 後,存至 localStorage。
目前先用程式動態產生 key 的方式,之後有機會再來研究產生公私鑰。
動態產生 key 的話,在驗證 jwt 時,如果有將 container 容器重啟的話,那麼原來產生的 jwt 自然就會驗證不通過,因為 key 已經變了。
在 webmix_api 資料夾底下,建立 apiKey.ts 檔案,內容如下:
// 產生 key
export const key = await crypto.subtle.generateKey(
{ name: "HMAC", hash: "SHA-256" },
true,
["sign", "verify"],
);
開啟 resolvers.ts 檔案,最上方加底下這行:
import { key } from "./apiKey.ts";
然後多一個函式如下,取得特定 email 的使用者:
async function getUser(email){
return await client.query("SELECT * FROM users WHERE email = '" + email + "'");
}
然後原來的 authUser 函式,改寫如下,主要會有 密碼驗證的功能,以及若密碼驗證通過,那就產生 JWT 回傳:
async function authUser(args){
let user_data = await getUser(args.username);
//console.log(user_data[0].password);
if(user_data.length > 0){
// 解密
const pwd_result = await bcrypt.compare(args.password, user_data[0].password);
if(pwd_result){ // 密碼核對通過,回傳 JWT
// 產生 jwt
let jwt = await create({ alg: "HS256", typ: "JWT" }, {
id: user_data[0].id,
nickname: user_data[0].nickname,
exp: getNumericDate(60 * 60)}, key
);
return jwt;
}
}
return "false";
}
在 webmix_efficiency 資料夾下,src/views/Home.vue 檔案,在 script 標籤內,加上以下的程式:
這段程式,主要有幾個用途:
<script>
export default {
data(){
return {
email: "",
password: ""
};
},
methods: {
auth_user(){
fetch("http://localhost:8080/graphql", {
method: 'POST',
body: JSON.stringify({
query: `mutation {
authUser(username: "${this.email}", password: "${this.password}")
}`
})
}).then(res => res.json()).then(data => {
if(data.data !== null && data.data.authUser !== "false"){
localStorage.setItem("jwt", data.data.authUser);
alert("登入成功");
location.reload();
}else{
alert("登入失敗");
}
});
}
}
}
</script>
然而在 template 標籤內,以下這行:
input(type="text")
改成:
input(type="text" v-model="email")
以下這行:
input(type="password")
改成:
input(type="password" v-model="password")
以下這行:
button(type="button") 登入
改成:
button(type="button" @click="auth_user") 登入
改完後,就可以實際測試看看囉,在登入頁面,輸入帳、密,按下登入按鈕,成功的話,就會跳成功的 alert,然後頁面會重新整理,就可以看看 localStorage 是否有 JWT 喔,如下圖藍框處:
太好了,有存下來了。
存下 JWT 之後,後續就可以檢查目前使用者的登入狀態囉。倒數十天了!